package com.code2roc.xhood.plugin;

import com.code2roc.xhood.model.*;
import com.code2roc.xhood.util.CommonUtil;
import com.code2roc.xhood.util.ObscureUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.objectweb.asm.MethodTooLargeException;

import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

@Mojo(name = "obscure", defaultPhase = LifecyclePhase.COMPILE)
public class ObscurePlugin extends AbstractMojo {
    @Parameter(name = "output", defaultValue = "${project.build.directory}")
    private File output;
    @Parameter(name = "packageName", defaultValue = "")
    private String packageName;
    @Parameter(name = "obscurePackages", defaultValue = "")
    private List<String> obscurePackages;
    @Parameter(name = "obscureIgnorePackages", defaultValue = "")
    private List<String> obscureIgnorePackages;
    @Parameter(name = "obscureIgnoreClasss", defaultValue = "")
    private List<String> obscureIgnoreClasss;

    @Parameter(name = "obscureClass", defaultValue = "true")
    private boolean obscureClass = true;
    @Parameter(name = "obscureClassPackages", defaultValue = "")
    private List<String> obscureClassPackages;
    @Parameter(name = "obscureClassIgnorePackages", defaultValue = "")
    private List<String> obscureClassIgnorePackages;
    @Parameter(name = "obscureClassIgnoreClasss", defaultValue = "")
    private List<String> obscureClassIgnoreClasss;

    @Parameter(name = "obscureMethod", defaultValue = "true")
    private boolean obscureMethod = true;
    @Parameter(name = "obscureMethodPackages", defaultValue = "")
    private List<String> obscureMethodPackages;
    @Parameter(name = "obscureMethodIgnorePackages", defaultValue = "")
    private List<String> obscureMethodIgnorePackages;
    @Parameter(name = "obscureMethodIgnoreClasss", defaultValue = "")
    private List<String> obscureMethodIgnoreClasss;

    @Parameter(name = "obscureField", defaultValue = "true")
    private boolean obscureField = true;
    @Parameter(name = "obscureFieldPackages", defaultValue = "")
    private List<String> obscureFieldPackages;
    @Parameter(name = "obscureFieldIgnorePackages", defaultValue = "")
    private List<String> obscureFieldIgnorePackages;
    @Parameter(name = "obscureFieldIgnoreClasss", defaultValue = "")
    private List<String> obscureFieldIgnoreClasss;

    @Parameter(name = "obscureLocal", defaultValue = "true")
    private boolean obscureLocal = true;
    @Parameter(name = "obscureLocalPackages", defaultValue = "")
    private List<String> obscureLocalPackages;
    @Parameter(name = "obscureLocalIgnorePackages", defaultValue = "")
    private List<String> obscureLocalIgnorePackages;
    @Parameter(name = "obscureLocalIgnoreClasss", defaultValue = "")
    private List<String> obscureLocalIgnoreClasss;

    @Parameter(name = "obscureParamter", defaultValue = "true")
    private boolean obscureParamter = true;
    @Parameter(name = "obscureParamterPackages", defaultValue = "")
    private List<String> obscureParamterPackages;
    @Parameter(name = "obscureParamterIgnorePackages", defaultValue = "")
    private List<String> obscureParamterIgnorePackages;
    @Parameter(name = "obscureParamterIgnoreClasss", defaultValue = "")
    private List<String> obscureParamterIgnoreClasss;

    @Parameter(name = "obscureConstant", defaultValue = "true")
    private boolean obscureConstant = true;
    @Parameter(name = "obscureConstantPackages", defaultValue = "")
    private List<String> obscureConstantPackages;
    @Parameter(name = "obscureConstantIgnorePackages", defaultValue = "")
    private List<String> obscureConstantIgnorePackages;
    @Parameter(name = "obscureConstantIgnoreClasss", defaultValue = "")
    private List<String> obscureConstantIgnoreClasss;

    @Parameter(name = "obscurePackage", defaultValue = "true")
    private boolean obscurePackage = true;
    @Parameter(name = "obscurePackageIgnorePackages", defaultValue = "")
    private List<String> obscurePackageIgnorePackages;


    private List<String> defineList = new ArrayList<>();
    private List<String> checkClassList = new ArrayList<>();
    private LinkedHashMap<String, String> defineMap = new LinkedHashMap<>();
    private HashMap<String, List<String>> methodAnnotationMap = new HashMap<>();
    private HashMap<String, String> sourceMap = new HashMap<>();
    private List<File> deleteFileList = new ArrayList<>();
    private String key = "";

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("【ObscurePlugin】:=========================start========================");
        Date startDate = new Date();
        key = CommonUtil.generateRandomString();
        File root = output;
        if (!root.exists()) {
            root.mkdirs();
        }
        if (obscurePackages == null) {
            obscurePackages = new ArrayList<>();
        }
        if (obscurePackages.size() == 0) {
            obscurePackages.add(packageName);
        }

        ObscureConfig obscureConfig = new ObscureConfig();
        obscureConfig.setPackageName(packageName);
        obscureConfig.setObscurePackages(obscurePackages);
        obscureConfig.setObscureIgnorePackages(obscureIgnorePackages);
        obscureConfig.setObscureIgnoreClasss(obscureIgnoreClasss);
        obscureConfig.setOutPutPath(output.getAbsolutePath());

        Date partStartDate = new Date();
        ClassRelationManage.init(output.getAbsolutePath(), root);
        System.out.println("【ObscurePlugin】:init Class Relation Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));

        ///region obscureMethod
        if (obscureMethod) {
            obscureConfig.setObscureOptionPackages(obscureMethodPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureMethodIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureMethodIgnoreClasss);
            partStartDate = new Date();
            doExecuteDefineMethodAnnotation(root);
            System.out.println("【ObscurePlugin】:doExecuteDefineMethodAnnotation Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteDefineMethod(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteDefineMethod Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteInvokeMethod(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteInvokeMethod Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            defineList.clear();
        }
        ///endregion

        ///region obscureField
        if (obscureField) {
            obscureConfig.setObscureOptionPackages(obscureFieldPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureFieldIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureFieldIgnoreClasss);
            partStartDate = new Date();
            doExecuteDefineField(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteDefineField Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteInvokeField(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteInvokeField Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        ///region obscureLocal
        if (obscureLocal) {
            obscureConfig.setObscureOptionPackages(obscureLocalPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureLocalIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureLocalIgnoreClasss);
            doExecuteLocalVariable(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteLocalVariable Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        ///region obscureParamter
        if (obscureParamter) {
            obscureConfig.setObscureOptionPackages(obscureParamterPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureParamterIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureParamterIgnoreClasss);
            partStartDate = new Date();
            doExecuteParamter(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteParamter Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        ///region obscureConstant
        if (obscureConstant) {
            obscureConfig.setObscureOptionPackages(obscureConstantPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureConstantIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureConstantIgnoreClasss);
            partStartDate = new Date();
            doExecuteConstant(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteConstant Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteCreateConstantUtil();
            System.out.println("【ObscurePlugin】:doExecuteCreateConstantUtil Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        ///region obscureClass
        if (obscureClass) {
            obscureConfig.setObscureOptionPackages(obscureClassPackages);
            obscureConfig.setObscureOptionIgnorePackages(obscureClassIgnorePackages);
            obscureConfig.setObscureOptionIgnoreClasss(obscureClassIgnoreClasss);
            partStartDate = new Date();
            doExecuteDefineClass(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteDefineClass Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteDeleteFile();
            System.out.println("【ObscurePlugin】:DeleteFile Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));

            ///region sort key
            LinkedHashMap<String, String> copData = new LinkedHashMap();
            copData.putAll(defineMap);
            List<String> replaceKeyList = new ArrayList<>();
            for (String key : defineMap.keySet()) {
                replaceKeyList.add(key);
            }
            replaceKeyList.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o2.length() - o1.length();
                }
            });
            defineMap.clear();
            for (String key : replaceKeyList) {
                defineMap.put(key, copData.get(key));
            }
            ///endregion

            partStartDate = new Date();
            doExecuteDefineUseClass(root);
            System.out.println("【ObscurePlugin】:doExecuteDefineUseClass Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteInvokeClass(root);
            System.out.println("【ObscurePlugin】:doExecuteInvokeClass Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        ///region obscurePackage
        if (obscurePackage) {
            sourceMap.clear();
            defineMap.clear();
            checkClassList.clear();
            obscureConfig.setObscureOptionIgnorePackages(obscurePackageIgnorePackages);
            partStartDate = new Date();
            doExecuteDefinePackage(root, obscureConfig);
            System.out.println("【ObscurePlugin】:doExecuteDefinePackage Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteDeleteFile();
            System.out.println("【ObscurePlugin】:DeleteFile Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));

            ///region sort key
            LinkedHashMap<String, String> copData = new LinkedHashMap();
            copData.putAll(defineMap);
            List<String> replaceKeyList = new ArrayList<>();
            for (String key : defineMap.keySet()) {
                replaceKeyList.add(key);
            }
            replaceKeyList.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o2.length() - o1.length();
                }
            });
            defineMap.clear();
            for (String key : replaceKeyList) {
                defineMap.put(key, copData.get(key));
            }
            ///endregion

            partStartDate = new Date();
            doExecuteDefineUseClass(root);
            System.out.println("【ObscurePlugin】:doExecuteDefineUsePackage Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
            partStartDate = new Date();
            doExecuteInvokeClass(root);
            System.out.println("【ObscurePlugin】:doExecuteInvokepPackage Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));

            partStartDate = new Date();
            doClearEmptyPackage(root);
            System.out.println("【ObscurePlugin】:doClearEmptyPackage Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }

        ///endregion

        ///region obscureField Enum
        if (obscureField) {
            partStartDate = new Date();
            doExecuteEnumAnnotationField(root, defineMap);
            System.out.println("【ObscurePlugin】:doExecuteEnumAnnotationField Finish,Execute Unit:" + CommonUtil.getExecuteUnitInfo(partStartDate));
        }
        ///endregion

        System.out.println("Total Execute Unit:" + CommonUtil.getExecuteUnitInfo(startDate));
        System.out.println("【ObscurePlugin】:=========================end========================");
    }

    public void doExecuteDefineClass(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefineClass(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class") && !checkClassList.contains(root.getAbsolutePath())) {
            checkClassList.add(root.getAbsolutePath());
            FileOutputStream fos = null;
            try {
                ObscureClassDefine obscureDefine = ObscureUtil.doObscureDefineClass(root, obscureConfig);
                if (obscureDefine.isModify()) {
                    defineMap.putAll(obscureDefine.getModifyMap());
                    sourceMap.putAll(obscureDefine.getSourceMap());
                    String newClassFilePath = root.getParentFile().getAbsolutePath() + File.separator + ObscureUtil.getObscureNameV1(className, ObsureEnum.Class) + ".class";
                    checkClassList.add(newClassFilePath);
                    File newClassFile = new File(newClassFilePath);
                    if (!newClassFile.exists()) {
                        newClassFile.createNewFile();
                    }
                    final byte[] instrumentBytes = obscureDefine.getData();
                    fos = new FileOutputStream(newClassFile);
                    fos.write(instrumentBytes);
                    fos.flush();
                    fos.close();
                    fos = null;
                    deleteFileList.add(root);
                } else {
                    final byte[] instrumentBytes = obscureDefine.getData();
                    fos = new FileOutputStream(root);
                    fos.write(instrumentBytes);
                    fos.flush();
                    fos.close();
                    fos = null;
                }
            } catch (MethodTooLargeException e) {

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteDefineUseClass(File root) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefineUseClass(file);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureDefineClassUse(root, defineMap, sourceMap);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteInvokeClass(File root) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteInvokeClass(file);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureInvokeClass(root, defineMap);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteDefinePackage(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefinePackage(file, obscureConfig);
            }
        }
        if (root.getName().endsWith(".class") && !checkClassList.contains(root.getAbsolutePath())) {
            checkClassList.add(root.getAbsolutePath());
            FileOutputStream fos = null;
            try {
                ObscurePackageDefine obscureDefine = ObscureUtil.doObscureDefinePackage(root, obscureConfig);
                if (obscureDefine.isModify()) {
                    defineMap.putAll(obscureDefine.getModifyMap());
                    String packagePath = obscureDefine.getPackagePath();
                    File packageFolder = new File(packagePath);
                    if (!packageFolder.exists()) {
                        packageFolder.mkdirs();
                    }
                    String classPath = obscureDefine.getClassPath();
                    checkClassList.add(classPath);
                    File newClassFile = new File(classPath);
                    if (!newClassFile.exists()) {
                        newClassFile.createNewFile();
                    }
                    final byte[] instrumentBytes = obscureDefine.getData();
                    fos = new FileOutputStream(newClassFile);
                    fos.write(instrumentBytes);
                    fos.flush();
                    fos.close();
                    fos = null;
                    deleteFileList.add(root);
                } else {
                    final byte[] instrumentBytes = obscureDefine.getData();
                    fos = new FileOutputStream(root);
                    fos.write(instrumentBytes);
                    fos.flush();
                    fos.close();
                    fos = null;
                }
            } catch (MethodTooLargeException e) {

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doClearEmptyPackage(File root) {
        if (root.isDirectory()) {
            File[] fileList = root.listFiles();
            for (File file : root.listFiles()) {
                doClearEmptyPackage(file);
            }
            fileList = root.listFiles();
            if (fileList.length == 0) {
                root.delete();
            }
        }
    }

    public void doExecuteDefineMethodAnnotation(File root) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefineMethodAnnotation(file);
            }
        }
        if (root.getName().endsWith(".class")) {
            try {
                HashMap<String, List<String>> definInfo = ObscureUtil.doObscureDefineMethodAnnotion(root);
                methodAnnotationMap.putAll(definInfo);
            } catch (Exception e) {

            }
        }
    }

    public void doExecuteDefineMethod(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefineMethod(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                ObscureDefine obscureDefine = ObscureUtil.doObscureDefineMethod(root, obscureConfig, methodAnnotationMap);
                defineList.addAll(obscureDefine.getDefineList());
                final byte[] instrumentBytes = obscureDefine.getData();
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (MethodTooLargeException e) {

            } catch (Exception e) {

                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteInvokeMethod(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteInvokeMethod(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureInvokeMethod(root, obscureConfig, defineList);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteDefineField(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteDefineField(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                ObscureDefine obscureDefine = ObscureUtil.doObscureDefineField(root, obscureConfig);
                defineList.addAll(obscureDefine.getDefineList());
                final byte[] instrumentBytes = obscureDefine.getData();
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteEnumAnnotationField(File root, LinkedHashMap<String, String> modifyMa) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteEnumAnnotationField(file, modifyMa);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureEnumAnnotationField(root, modifyMa);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteInvokeField(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteInvokeField(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureInvokeField(root, obscureConfig, defineList);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteLocalVariable(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteLocalVariable(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureLocalVariable(root, obscureConfig);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteParamter(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteParamter(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureParamter(root, obscureConfig);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteConstant(File root, ObscureConfig obscureConfig) {
        if (root.isDirectory()) {
            for (File file : root.listFiles()) {
                doExecuteConstant(file, obscureConfig);
            }
        }
        String className = root.getName().replace(".class", "");
        if (root.getName().endsWith(".class")) {
            FileOutputStream fos = null;
            try {
                final byte[] instrumentBytes = ObscureUtil.doObscureConstant(root, obscureConfig, key);
                fos = new FileOutputStream(root);
                fos.write(instrumentBytes);
                fos.flush();
            } catch (Exception e) {
                System.out.println("【Obscure-Exception】:" + className);
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {

                    }
                }
            }
        }
    }

    public void doExecuteCreateConstantUtil() {
        FileOutputStream fos = null;
        try {
            byte[] instrumentBytes = ObscureUtil.createConstantUtilClassFile(packageName, key);
            String fileName = output + "/classes/" + packageName.replace(".", "/") + "/" + "ConstantUtil.class";
            File file = new File(fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            fos = new FileOutputStream(file);
            fos.write(instrumentBytes);
            fos.flush();
        } catch (Exception e) {
            System.out.println("【Obscure-Exception】:doExecuteCreateConstantUtil");
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {

                }
            }
        }
    }

    public void doExecuteDeleteFile() {
        for (int i = 0; i < deleteFileList.size(); i++) {
            File file = deleteFileList.get(i);
            doDeleteFile(file);
        }
        deleteFileList.clear();
    }

    public void doDeleteFile(File file){
        boolean result = file.delete();
        if(!result){
            System.gc();
            if(! file.delete()){
                doDeleteFile(file);
            }
        }
    }
}
